<template>
  <div 
    :id="smallType ? 'smallType' : 'largeType'" 
    ref="attrSlots"
    class="v-attrSlots"
  >
    <div :class="smallType ? '_smallType' : '_largeType'" class="_attrSlots-container">
      <div class="g-jc-sb _header g-flex-0">
        <div class="g-ai-c">
          <img :src="selectedElement && selectedElement.iconPath" alt="" style="margin-right: 4px">
          <span style="font-size:12px; color: #000">
            {{type}}
          </span>
        </div>
        <div class="g-ai-c">
          <span class="_sort _img-btn" @click="activeKey = keys">
            <img src='statics/icons/app/iconspread.svg'/>
          </span>
          <div class="divider"></div>
          <span class="_sort _img-btn" @click="activeKey = []">
            <img src='statics/icons/app/iconshrink.svg'/>
          </span>
          <div class="divider"></div>
          <span class="_sort _img-btn" :class="{'_sort-active':sortActive}" @click="handleSort">
            <img src='statics/icons/app/textsort.png'/>
          </span>
        </div>   
      </div>
      <main @click="clickMain">
        <div class="_col" style="height: 30px;">
          <div class="_col-left" style="line-height: 30px">名称</div>
          <div class="_col-middle" style="line-height: 30px">值</div>
        </div>
        <a-collapse v-model="activeKey">
          <template #expandIcon>
            <img src="statics/icons/app/arrow2.png" alt="">
          </template>
          <a-collapse-panel v-for="item in sortData" :key="item.id">
            <span slot="header">
              <img :src="item.node.iconPath" alt="" style="margin-right: 4px">
              <span>{{item.node.name}}</span>
            </span>
            <div
              v-for="child in item.children"
              :key="child.id"
              class="_col"
              :class="{_selected: selectedRow ===  child.id}"
              @click="selectRow($event, child.id)">
              <div class="_col-left" :title="child.name">
                <img :src="iconPath[child.id] || child.iconPath" alt="" style="margin-right: 4px">
                <span>{{child.name}}</span>
              </div>
              <div class="_col-middle">
                <div v-for="(valueObj, index) in values[child.id]" :key="index" class="_value-box">
                  <a-input
                    v-if="selectedType[valueObj.typeName].type === 'input'"
                    v-focus
                    :value="valueObj.value"
                    :data-focus="valueObj.focus"
                    @pressEnter="handlePressEnter"
                    @blur="e => updateValue(e, valueObj, child, index)"/>
                  <span v-if="selectedType[valueObj.typeName].type === 'tree-single-select'">
                    <img :src="valueObj.iconPath" alt="">
                    <span>{{valueObj.value}}</span>
                  </span>
                  <a-select v-if="selectedType[valueObj.typeName].type === 'switch1'" :default-value="valueObj.value">
                    <a-select-option v-for="(item, index) in getSelectOptions(child)" :key="item.id" :value="index">
                      {{item.name}}
                    </a-select-option>
                  </a-select>
                  <a-checkbox
                    v-else-if="selectedType[valueObj.typeName].type === 'switch'"
                    size="small"
                    :checked="valueObj.value"
                    @change="e => updateValue(e, valueObj, child, index)">
                    {{ !!valueObj.value }}
                  </a-checkbox>
                  <img src="statics/icons/app/icondelete2.png" alt="" @click="deleteValue(valueObj, child, index)">
                </div>
              </div>
              <div class="_col-right">
                <img src="statics/icons/app/iconadd3.png" alt="" style="cursor: pointer" @click.stop="addValue(child)">
              </div>
            </div>
          </a-collapse-panel>
        </a-collapse>
      </main>
    </div>
    
  </div>
</template>
<script>
import Property from './Property';
import { PropertyUtil } from './PropertyUtil';
import { graphHelper } from 'src/api/GraphHelper';
import { SysMLUtilHelper, UMLClassificationHelper } from "src/api/sysml-imports";
import { actions, OpenCreateElementAction } from '@/pages/mxgraph/Actions';
import { selectMutiple } from 'components/Attribute/modals/SelectMutiple.vue';
import { GraphNodeUtil } from '@/pages/mxgraph/GraphNodeUtil';
import { valuetypes } from '@/components/Attribute/config/index';
import { selectValue } from '@/components/Attribute/modals/SelectValue.vue';

const extraValuetypes = [
  { label: '枚举值', value: 'EnumerationLiteral', type: 'switch', diabled: true }
];

export default {
  name: 'attr-slots',
  components: {
    'm-property': Property
  },
  directives: {
    focus: {
      //// 指令的定义
      inserted: function (el) {
        if (el.dataset['focus'] === '1') {
          el.focus();
        }
      },
    },
  },
  props: {
    property: Object, //// 当前选中元素的property
    smallType: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      valuetypes: [...valuetypes, ...extraValuetypes],
      sortActive: false,
      type: '',
      activeKey: [],
      keys: [], //// 存储dataList中的id
      dataList: [],
      values: {}, //// 根据id存储slot的值
      selectedRow: '',
      iconPath: {}, //// 创建slot时改变icon
    };
  },
  computed: {
    selectedElement(){
      return app.selectedElement;
    },

    selectedType(){
      const selectedType = {};
      this.valuetypes.forEach(item => {
        selectedType[item.value] = item;
      });
      return selectedType;
    },
    
    sortData() {
      let dataList = [...this.dataList];
      if (this.sortActive) {
        dataList.sort((a, b) => ('' + a.node.name).localeCompare(b.node.name));
      }
      return dataList;
    },
  },
  watch: {
    selectedElement: {
      handler(val){
        if (val) {
          const type = val.getTypeName();
          this.type = app.activeProject.configManager.getTypeNameConfig()[type]?.cnName || '';
          console.log('type', type);
          if (type === 'InstanceSpecification' || type === 'Instance') {
            this.initData();
          }
          
        }
      },
      immediate: true
    }
  },
  created() {
    //// this.initData();
  },
  mounted() {
   
  },
  methods: {
    //// 初始化信息
    initData() {
      this.sortActive = false;
      
      this.getData();
    },
    getData() {
      if (!this.selectedElement) {
        return;
      }
      const dataList = [];
      const keys = [];
      const model = this.selectedElement.model;
      const classifiers = model.getClassifiers().toArray();
      const slots = this.selectedElement.getInstanceSlots().toArray();
      const slotsObj = {};
      const ids = {}; //// 用于存储allAttributes元素的父级id，防止重复添加

      //// 遍历slots，查找到id对应的slot值
      slots.forEach(slot => {
        console.log('slot', slot);
        GraphNodeUtil.initProperty(slot);
        const node = slot.model.definingFeature;
        if (!slot.model.values) return;
        let children = slot.getChildren();
        const values = children.map(child => {
          return { 
            focus: 0, 
            value: this.getValue(slot, child),
            iconPath: 'statics/images/sysml/InstanceSpecification.svg',
            valueSpecification: child, 
            typeName: child.model.typeName
          };
        });
        slotsObj[node.id] = { values, slot };
      });
      console.log('slotsObj', slotsObj, slots);

      classifiers.forEach(classifier => {
        const node = graphHelper.getGraphNodeById(classifier.id, app.activeProjectId);
        const allAttributes = node.getAllAttributes().toArray();
        allAttributes.forEach(attribute => {
          const parentNode = attribute.container;
          const data = {};
          if (!ids[parentNode.id]) {
            ids[parentNode.id] = {
              childrenIds: {},
              data
            };
            data.node = parentNode;
            data.id = parentNode.id;
            data.children = [];
            keys.push(parentNode.id);
            dataList.push(data);
          }
          const childrenIds = ids[parentNode.id].childrenIds;
          if (!childrenIds[attribute.id]) {
            childrenIds[attribute.id] = true;
            ids[parentNode.id].data.children.push(attribute);

            if (slotsObj[attribute.id]) {
              this.$set(this.iconPath, attribute.id, 'statics/images/sysml/Slot.svg');
              attribute._slot = slotsObj[attribute.id].slot; //// 将slot指向存入到attribute中
            }
            this.$set(this.values, attribute.id, slotsObj[attribute.id] ? slotsObj[attribute.id].values : []);
          }
        });
        console.log('allAttributes', allAttributes);
        
      });
      this.dataList = dataList;
      this.keys = keys;
      this.activeKey = keys;
      console.log('dataList', dataList);
    },

    //// 根据不同类型不同，显示value
    getValue(slot, node) {
      //// const typeName = UMLClassificationHelper.getSlotTypeName(slot.model);
      const typeName = node.model.typeName;
      const value = SysMLUtilHelper.getValueSpecificationValue(node.model);
      console.log('value', node, value);
      let result;
      if (typeName === 'ElementValue' || typeName === 'InstanceValue') {
        result = node.displayTitle;
      } else if (typeName === 'LiteralNull') {
        result = '';
      } else {
        result = value;
      }
      if (typeName === "LiteralUnlimitedNatural") {
        if (result < 0) {
          result = '*';
        }
      }
      console.log('result', result);
      return result;
    },

    //// 添加新的值
    addValue(node) {
      const linkedType = PropertyUtil.getNodePropertyValue(node, 'Type');
      console.log('linkedType', linkedType );
      this.addSlot(node);
      const typeName = UMLClassificationHelper.getSlotTypeName(node._slot.model);
      console.log('typeName', typeName, node._slot);
      this.selectedRow = node.id;
      if (typeName === 'InstanceValue' && linkedType.typeName !== 'Enumeration') {
        selectMutiple
          .popup({
            isNodeSelectable: (node) => this.filterElements(node, linkedType),
            filterCondtion: '1',
            currentIds: []
          })
          .then((res) => {
            console.log('res', res);
            const values = [];
            res.forEach(result => {
              const valueSpecification = this.addSlotValue(node, typeName);
              UMLClassificationHelper.updateValueSpecification(valueSpecification.model, result.graphNode.model);
              const value = { 
                value: result.graphNode.name, 
                valueSpecification, 
                typeName,
                iconPath: 'statics/images/sysml/InstanceSpecification.svg' 
              };
              values.push(value);
            });
            this.values[node.id] = this.values[node.id].concat(values);
          })
          .catch((e) => {
            e && console.error(e);
          }).finally(() => {
            if (this.values[node.id].length === 0) {
              node._slot.remove();
              this.$set(this.iconPath, node.id, '');
            }
            this.afterValueSpecification();
          });
      } else if (typeName === 'InstanceValue' && linkedType.typeName === 'Enumeration') {
        selectValue.popup({
          isNodeSelectable: (node) => this.filterInstance(node, linkedType),
          filterCondtion: '1',
          currentIds: []
        })
          .then((res) => {
            console.log('res', res);
            const valueSpecification = this.addSlotValue(node, typeName);
            UMLClassificationHelper.updateValueSpecification(valueSpecification.model, res.graphNode.model);
            const value = { 
              value: res.graphNode.name, 
              valueSpecification, 
              typeName, 
              iconPath: 'statics/images/sysml/InstanceSpecification.svg' 
            };
            this.values[node.id].push(value);
          })
          .catch((e) => {
            e && console.error(e);
          }).finally(() => {
            if (this.values[node.id].length === 0) {
              node._slot.remove();
              this.$set(this.iconPath, node.id, '');
            }
            this.afterValueSpecification();
          });
      } else {
        const valueSpecification = this.addSlotValue(node, typeName);
        console.log('valueSpecification',  valueSpecification);
        this.values[node.id].push({ value: valueSpecification.model.value, focus: 1, valueSpecification, typeName });
        this.afterValueSpecification();
      }
    },

    //// 添加valueSpecification后更新画布
    afterValueSpecification() {
      this.$bus.emit('fresh-graph');
      app.$bus.emit('project-modified');
    },

    addSlot(node) {
      const id = node.id;
      console.log('addSlot', this.values, id);
      if (this.values[id].length === 0) { //// 值为空时，创建slot
        console.log('创建slot');
        const newNode = this.selectedElement.addChildNode('Slot', app.activeProjectId);
        newNode.setDefiningFeature(node.model);
        node._slot = newNode;
        this.$set(this.iconPath, id, 'statics/images/sysml/Slot.svg');
        this.selectedElement.refreshCompartment(); //// 刷新
      }
    },

    //// 添加slot对应的值
    addSlotValue(node, typeName) {
      if (node._slot) {
        console.log('添加slot值', UMLClassificationHelper, node._slot);
        const slot = node._slot;
        const valueSpecification = slot.addChildNode(typeName, app.activeProjectId, true);
        return valueSpecification;
      }
    },

    filterElements(node, linkedType) {
      const type = node.getTypeName();
      if (type === 'InstanceSpecification' || type === 'Instance') {
        const classifiers = node.model.getClassifiers().toArray();
        for (let i = 0; i < classifiers.length; i++) {
          const classifier = classifiers[i];
          if (classifier.id === linkedType.id) {
            return true;
          }
        }
        console.log(classifiers, linkedType);
        return false;
      } else {
        return false;
      }
    },

    //// 过滤枚举值
    filterInstance(node, linkedType) {
      const type = node.getTypeName();
      const enumerations = linkedType.ownedLiterals.toArray();
      const ids = enumerations.map(item => item.id);
      if (type === 'EnumerationLiteral') {
        if (ids.includes(node.id)) {
          return true;
        }
      }
      return false;
    },

    deleteValue(valueObj, child, index) {
      const id = child.id;
      this.values[id].splice(index, 1);
      valueObj.valueSpecification.remove();
      if (this.values[id].length === 0) { //// 值为空时，删除slot
        console.log('删除slot');
        child._slot.remove();
        this.$set(this.iconPath, id, '');
      }
      this.$bus.emit('fresh-graph');
    },

    //// 点击单元格，改变背景色
    selectRow(e, id) {
      this.selectedRow = id;
    },

    handleSort() {
      this.sortActive = !this.sortActive;
    },

    handlePressEnter(e) {
      e.target.blur();
    },

    clickMain(e) { //// 清空selectedRow
      if (e.target.nodeName === 'MAIN') {
        this.selectedRow = '';
      }
    },

    //// 设置slot的值
    updateValue(e, valueObj, child, index) {
      const id = child.id;
      let value = e.target.value;
      if (valueObj.typeName === 'LiteralBoolean') {
        value = e.target.checked;
      }
      const isOk = this.judgeValueType(valueObj.typeName, value);
      if (!isOk) return;
      if (value !== valueObj.value) {
        console.log('设置value', value,  valueObj);
        const currentValueObj = this.values[id][index];
        UMLClassificationHelper.updateValueSpecification(valueObj.valueSpecification.model, value);
        if (valueObj.typeName === "LiteralUnlimitedNatural") {
          if (value < 0) {
            this.$set(this.values[id], index, { ...currentValueObj, value: '*' });
            return;
          }
        }
        this.$set(this.values[id], index, { ...currentValueObj, value });
        this.$bus.emit('fresh-graph');
      }
    },

    judgeValueType(typeName, value) {
      if (typeName === 'LiteralInteger') {
        if (isNaN(value) || value % 1 !== 0) {
          this.$messageBox.error({ id: 100, text: '需要一个整数' });
          return false;
        }
      }

      if (typeName === 'LiteralReal') {
        if (isNaN(value)) {
          this.$messageBox.error({ id: 100, text: '需要一个数字' });
          return false;
        }
      }

      if (typeName === 'LiteralUnlimitedNatural') {
        if (isNaN(value) && value !== '*') {
          this.$messageBox.error({ id: 100, text: '需要一个数字' });
          return false;
        }
      }

      return true;
    },

    //// 获取枚举的成员
    getSelectOptions(node) {
      const linkedType = PropertyUtil.getNodePropertyValue(node, 'Type');
      const graphNode = graphHelper.getGraphNodeById(linkedType.id, app.activeProjectId);
      const members = graphNode.model.getOwnedMembers().toArray();
      console.log('members', members);
      return members;
    }

  }
};
</script>
<style lang="scss">
.v-attrSlots {
  padding: 8px;
  height: 100%;
  ::-webkit-scrollbar {
    width: 6px;
  }
  ._attrSlots-container {
    height: 100%;
    &._largeType {
      border-top: 1px solid #E4E3E3;
      border-bottom: 0;
    }
  }
._header {
		padding:4px 10px ;
    background:#D4EBF8;
    border-left: 1px solid #E4E3E3;
    border-right: 1px solid #E4E3E3;
    height: 30px;
    .divider {
      width: 1px;
      height: 16px;
      background: #B1CEE2;
      margin: 0 10px;
    }
    ._button-area {
      button {
        height: 24px;
        padding: 0 8px;
        border-radius: 0px;
        span {
          line-height: 16px;
        }
        & + button {
          margin-left: 8px;
        }
        img {
          margin-right: 3px;
        }
      }
    }
	}
	._sort {
    border: 1px solid #D4EBF8;
    vertical-align: middle;
		&._sort-active {
		  background: linear-gradient(180deg, #B9E3FF 0%, #47B3FF 55%, #80C8FE 100%);
      border: 1px solid #B1CEE2;
		}
	}
	._img-btn {
		display: inline-block;
		box-sizing: border-box;
		cursor: pointer;
		img {
			display: block;
			height: 14px;
			width: 14px;
		}
		&:hover {
      background: linear-gradient(180deg, #E7F5FE 0%, #B0DEFF 65%, #B2DDFD 100%);
      border: 1px solid #B1CEE2;
		}
		&:active {
      background: linear-gradient(180deg, #B9E3FF 0%, #47B3FF 55%, #80C8FE 100%);
      border: 1px solid #B1CEE2;
		}
  }
  main {
    overflow: auto;
    height: calc(100% - 30px);
    ._col {
      min-height: 25px;
      border: 1px solid #E4E3E3;
      border-top: 1px solid #fff;
      display: flex;
      font-size: 12px;
      color: #000000;
      &._selected {
        border-color: #3483B8;
        ._col-left {
          background-color: #3483B8;
          color: #fff;
        }
      }
      ._col-left {
        width: 118px;
        line-height: 25px;
        padding-left: 10px;
        border-right: 1px solid #E4E3E3;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
      ._col-middle {
        flex: 1;
        line-height: 25px;
        padding-left: 10px;
        ._value-box {
          height: 25px;
          display: flex;
          padding: 2px 0;
          margin-left: -10px;
          border-bottom: 1px solid #E4E3E3;
          &:last-of-type {
            height: 24px;
            border-bottom: 0;
          }
          input {
            flex: 1;
            border: 0;
            padding: 0;
            padding-left: 10px;
            height: 20px;
            color: #000;
            &:focus {
              border:0;
              box-shadow: unset;
            }
          }
          .ant-checkbox-wrapper {
            flex: 1;
            padding-left: 10px;
            span {
              color: #000;
            }
          }
          > span {
            flex: 1;
            padding-left: 10px;
            display: flex;
            align-items: center;
            img {
              margin-right: 4px;
            }
            > span {
              line-height: 1;
            }
          }
          > img {
            margin: 3px 5px;
            width: 14px;
            height: 14px;
            cursor: pointer;
          }
        }
      }
      ._col-right {
        width: 25px;
        line-height: 25px;
        padding-left: 5px;
        border-left: 1px solid #E4E3E3;
      }
    }
    .ant-collapse {
      border: 0;
      .ant-collapse-item {
        border: 0;
        .ant-collapse-header {
          height: 25px;
          background: #F2F2F2;
          border: 1px solid #E4E3E3;
          border-right: 1px solid #E4E3E3 !important;
          border-top: 0;
          padding-left: 10px !important;
          font-size: 12px;
          border-radius: 0;
          .ant-collapse-arrow {
            width: 12px;
            right: 6px;
            left: unset;
          }
        }
      .ant-collapse-content {
        border: 0;
        border-radius: 0;
        .ant-collapse-content-box {
          padding: 0;
        }
      }
    }
    }
    
  }
  &#smallType {
    background-color: #fff;
    padding: 0 4px 0 0;
    ._header {   
      border-bottom: 1px solid #B1CEE2;
      border-left: 0;
      border-right: 0;
    }
    ._col {
      border-left: 0;
      border-right: 0;
    }
  }
}
</style>
